package dreic;

//############################################################################
// The root of the tree node hierarchy

/**
 * Class Tree defines the type of all abstract syntax tree nodes.
 */
abstract class Tree {

  /**
   * The source code position of this tree node.
   * Has to be set explicitly with the setPos method
   */
  private var p: Int = Position.UNDEFINED;
  def pos: Int = p;
  def setPos(p: Int): this.type = { this.p = p; this }

}

//############################################################################
// Tree node representing a complete program

/**
 * P = Program { D } E
 */
case class Program(classes: List[ClassDef], statement: Stat)
     extends Tree;

//############################################################################
// Tree nodes for definitions

/**
 * A common superclass for all definitions
 */
abstract class Def extends Tree;

/**
 * D = ClassDef name [ name ] { M }
 */
case class ClassDef(name: Name , name2: Option[Name], membres: List[Member]) extends Def;


/**
 * A common superclass for member definitions
 */
abstract class Member extends Def;

/**
 * M = FieldDecl name T
 */
case class FieldDecl(name : Name, field_type : TypeTree) extends Member;

/**
 * M = MethodDef name { name T } T E
 */
case class MethodDef(name: Name, args: List[Pair[Name, TypeTree]], ret_type: Option[TypeTree], body : Expr) extends Member;

//############################################################################
// Tree nodes for types

/**
 * A common superclass for tree nodes designating types
 */
abstract class TypeTree extends Tree;

/**
 * T = Int
 */
case class IntType extends TypeTree;

/**
 * T = Null
 */
case class NullType extends TypeTree;

/**
 * T = ClassType name
 */
case class ClassType(name: Name) extends TypeTree;

//############################################################################
// Tree nodes for statements

/**
 * A common superclass for all statements
 */
abstract class Stat extends Tree;

/**
 * S = While E { S }
 */
case class While(cond: Expr, stats: List[Stat]) extends Stat;

/** 
* S = If E S S
*/
case class If(cond: Expr, iftrue: Stat, iffalse: Stat) extends Stat;

/**
 * S = Var name T E
 */
case class Var(varname: Name, vartype: TypeTree, init: Expr)
     extends Stat;

/**
 * S = Set name E
 */
case class Set(name: Name, expr: Expr) extends Stat;

/**
 * S = Do E
 */
case class Do(expr: Expr) extends Stat;

/**
 * S = PrintInt E
 */
case class PrintInt(expr: Expr) extends Stat;

/**
 * S = PrintChar E
 */
case class PrintChar(expr: Expr) extends Stat;
  
/**
* S = Compound { S }
*/
case class Compound(stats: List[Stat]) extends Stat;

//############################################################################
// Tree nodes for expressions

/**
 * A common superclass for expressions

E = Ident name
  | New name { E }
  | Select E name
  | Call E name { E }
  | IntLit int
  | NullLit
  | Unop U E
  | Binop B E E
  | ReadInt
  | ReadChar
  | Block { S } [ E ]
*/
abstract class Expr extends Tree;

case class Ident(name: Name) extends Expr;

case class New(name: Name, exprs: List[Expr]) extends Expr;

case class Select(expr: Expr, name: Name) extends Expr;

case class Call(expr: Expr, name: Name, exprs: List[Expr]) extends Expr;

case class IntLit(value: int) extends Expr;

case class NullLit() extends Expr;

case class Unop(op: U, expr: Expr) extends Expr;

case class Binop(op: B, left: Expr, right: Expr) extends Expr;
  
case class ReadInt() extends Expr;

case class ReadChar() extends Expr;

case class Block(stats: List[Stat], return_value: Option[Expr]) extends Expr;

//############################################################################

//############################################################################
// Tree nodes for operators

abstract class Operator extends Tree;
  
abstract class B extends Operator;
  
abstract class U extends Operator;
  
case class Not extends U{
  override def toString() = "!";
}
case class Neg extends U{
  override def toString() = "-";
}

case class Add extends B{
  override def toString() = "+";
}
case class Sub extends B{
  override def toString() = "-";
}
case class Mul extends B{
  override def toString() = "*";
}
case class Div extends B{
  override def toString() = "/";
}
case class Mod extends B{
  override def toString() = "%";
}
case class Eq extends B{
  override def toString() = "==";
}
case class Ne extends B{
  override def toString() = "<>";
}
case class Lt extends B{
  override def toString() = "<";
}
case class Le extends B{
  override def toString() = "<=";
}
case class Gt extends B{
  override def toString() = ">";
}
case class Ge extends B{
  override def toString() = ">=";
}
case class And extends B{
  override def toString() = "&&";
}
case class Or extends B {
  override def toString() = "||";
}

//############################################################################
